/*
 * Copyright (c) 2007 jNetX.
 * http://www.jnetx.com
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of
 * jNetX. You shall not disclose such Confidential Information and
 * shall use it only in accordance with the terms of the license
 * agreement you entered into with jNetX.
 *
 * $Id$
 */
package com.jnetx.javax.sip.header;

import javax.sip.InvalidArgumentException;
import javax.sip.header.SubscriptionStateHeader;
import java.text.ParseException;

/**
 * This interface represents the Subscription State header, as
 * defined by <a href = "http://www.ietf.org/rfc/rfc3265.txt">RFC3265</a>, this
 * header is not part of RFC3261.
 * <p/>
 * NOTIFY requests MUST contain SubscriptionState headers which indicate the
 * status of the subscription. The subscription states are:
 * <ul>
 * <li> active - If the SubscriptionState header value is "active", it means
 * that the subscription has been accepted and (in general) has been authorized.
 * If the header also contains an "expires" parameter, the subscriber SHOULD
 * take it as the authoritative subscription duration and adjust accordingly.
 * The "retry-after" and "reason" parameters have no semantics for "active".
 * <li> pending - If the SubscriptionState value is "pending", the
 * subscription has been received by the notifier, but there is insufficient
 * policy information to grant or deny the subscription yet. If the header also
 * contains an "expires" parameter, the subscriber SHOULD take it as the
 * authoritative subscription duration and adjust accordingly. No further
 * action is necessary on the part of the subscriber. The "retry-after" and
 * "reason" parameters have no semantics for "pending".
 * <li> terminated - If the SubscriptionState value is "terminated", the
 * subscriber should consider the subscription terminated. The "expires"
 * parameter has no semantics for "terminated". If a reason code is present, the
 * client should behave as described in the reason code defined in this Header.
 * If no reason code or an unknown reason code is present, the client MAY
 * attempt to re-subscribe at any time (unless a "retry-after" parameter is
 * present, in which case the client SHOULD NOT attempt re-subscription until
 * after the number of seconds specified by the "retry-after" parameter).
 * </ul>
 *
 * @author <a href="mailto:dparhonin@jnetx.ru">Dmitry Parhonin</a>
 * @version $Revision$
 */
public class SubscriptionStateHeaderImpl extends ParametrizedHeaderBase implements SubscriptionStateHeader {
    private final static SubscriptionStateHeaderParser parser = new SubscriptionStateHeaderParser();

    private String state;

    public SubscriptionStateHeaderImpl() {
        super(SubscriptionStateHeader.NAME);
    }

    SubscriptionStateHeaderImpl(byte[] data, int start, int end) {
        super(SubscriptionStateHeader.NAME, data, start, end);
    }

    public Object clone() {
        final SubscriptionStateHeaderImpl header = new SubscriptionStateHeaderImpl();
        header.cloneBase(this);
        if (parsed) {
            header.cloneParameters(this);
            header.state = this.state;
        }
        return header;
    }

    protected HeaderParser getParser() {
        return parser;
    }

    protected String getValueAsString() {
        return state;
    }

    /**
     * Sets the relative expires value of the SubscriptionStateHeader. The
     * expires value MUST be greater than zero and MUST be less than 2**31.
     *
     * @param expires the new expires value of this SubscriptionStateHeader.
     * @throws javax.sip.InvalidArgumentException
     *          if supplied value is less than zero.
     */
    public void setExpires(int expires) throws InvalidArgumentException {
        if (expires < 0)
            throw new InvalidArgumentException("The expires parameter cannot be less than zero!");
        try {
            setParameter("expires", Integer.toString(expires));
        } catch (ParseException e) {
            throw new InvalidArgumentException("Cannot set the expires parameter!", e);
        }
    }

    /**
     * Gets the expires value of the SubscriptionStateHeader. This expires value is
     * relative time.
     *
     * @return the expires value of the SubscriptionStateHeader.
     */
    public int getExpires() {
        final String expiresStr = getParameter("expires");
        int expires = -1;
        try {
            expires = Integer.parseInt(expiresStr);
        } catch (Exception ex) {
        }
        return expires;
    }

    /**
     * Sets the retry after value of the SubscriptionStateHeader. The retry after value
     * MUST be greater than zero and MUST be less than 2**31.
     *
     * @param retryAfter the new retry after value of this SubscriptionStateHeader
     * @throws javax.sip.InvalidArgumentException
     *          if supplied value is less than zero.
     */
    public void setRetryAfter(int retryAfter) throws InvalidArgumentException {
        if (retryAfter < 0)
            throw new InvalidArgumentException("The retryAfter parameter cannot be less than zero!");
        try {
            setParameter("retry-after", Integer.toString(retryAfter));
        } catch (ParseException e) {
            throw new InvalidArgumentException("Cannot set the retryAfter parameter!", e);
        }
    }

    /**
     * Gets the retry after value of the SubscriptionStateHeader. This retry after
     * value is relative time.
     *
     * @return the retry after value of the SubscriptionStateHeader.
     */
    public int getRetryAfter() {
        final String retryAfterStr = getParameter("retry-after");
        int retryAfter = -1;
        try {
            retryAfter = Integer.parseInt(retryAfterStr);
        } catch (Exception ex) {
        }
        return retryAfter;
    }

    /**
     * Gets the reason code of SubscriptionStateHeader.
     *
     * @return the comment of this SubscriptionStateHeader, return null if no reason code
     *         is available.
     */
    public String getReasonCode() {
        return getParameter("reason");
    }

    /**
     * Sets the reason code value of the SubscriptionStateHeader.
     *
     * @param reasonCode the new reason code string value of the SubscriptionStateHeader.
     * @throws java.text.ParseException which signals that an error has been reached
     *                                  unexpectedly while parsing the reason code.
     */
    public void setReasonCode(String reasonCode) throws ParseException {
        setParameter("reason", reasonCode);
    }

    /**
     * Gets the state of SubscriptionStateHeader.
     *
     * @return the state of this SubscriptionStateHeader.
     */
    public String getState() {
        parse();
        return state;
    }

    /**
     * Sets the state value of the SubscriptionStateHeader.
     *
     * @param state the new state string value of the SubscriptionStateHeader.
     * @throws java.text.ParseException which signals that an error has been reached
     *                                  unexpectedly while parsing the state.
     */
    public void setState(String state) throws ParseException {
        parse();
        this.state = state;
        invalidateHeaderData();
    }
}
/*
 * $Log$
 */